package org.qloudgen.borg.pages;

import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.AjaxSelfUpdatingTimerBehavior;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.ajax.markup.html.navigation.paging.AjaxPagingNavigator;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.FormComponent;
import org.apache.wicket.markup.html.form.Radio;
import org.apache.wicket.markup.html.form.RadioGroup;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.PageableListView;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.util.time.Duration;
import org.qloudgen.borg.CommonValues;
import org.qloudgen.borg.beans.CacheBean;
import org.qloudgen.borg.beans.FileBean;
import org.qloudgen.borg.beans.ResultBean;
import org.qloudgen.borg.beans.TaskBean;
import org.qloudgen.borg.beans.TaskListBean;
import org.qloudgen.borg.beans.UserBean;
import org.qloudgen.borg.messaging.message.TaskMessage;
import org.qloudgen.borg.metadb.DefaultImpl;
import org.qloudgen.borg.pages.common.BasePage;
import org.qloudgen.borg.pages.model.TaskModel;
import org.qloudgen.borg.pages.panel.ExportPanel;
import org.qloudgen.borg.task.TaskExecutor;
import org.qloudgen.borg.task.TaskRules;
import org.qloudgen.borg.task.TaskUtils;

import com.google.common.collect.Lists;

@SuppressWarnings({"unchecked","rawtypes"})
public class TaskListPage extends BasePage{

	/**
	 * @Author youngeryoyo
	 * youngeryoyo@gmail.com
	 */

	static Log log = LogFactory.getLog(TaskListPage.class);

	private static final long serialVersionUID = 1L;
	private transient List<TaskListBean> tasks = Lists.newArrayList();
	private transient String buttonName;
	private transient FileBean fileBean = new FileBean();
	private transient String cacheID,sql;
	private transient List<String> headers = Lists.newArrayList();
	private transient boolean flag = false;
	
	public TaskListPage(final PageParameters pageParameters){
		
		super();
		this.pp = pageParameters;
		
		// get tasks from metadb
		DefaultImpl.getTasks(tasks);
		
		// add form 
		Form<?> form = new Form("form",new CompoundPropertyModel<TaskModel>(new TaskModel())) {
			
			private static final long serialVersionUID = 1L;

			protected void onSubmit() {
				
				TaskListBean taskListBean = ((TaskModel)getDefaultModelObject()).getGroup();
				buttonName = ((FormComponent<String>)findSubmittingButton()).getInputName();
				
				if (taskListBean == null && !buttonName.equalsIgnoreCase("clearLog")) {	info(CommonValues.INFO_NO_SELECT);  return; } 
				
				if (buttonName.equals("reSubmit")) {

					CacheBean cache = new CacheBean().setClusterID(taskListBean.getClusterID())
							 .setDsNo(taskListBean.getDsNo())
	                         .setFuncNo(taskListBean.getFuncNo())
	                         .setParams(taskListBean.getParams())
	                         .setReload(taskListBean.getReload().equalsIgnoreCase("true")?true:false);
					
					if (!TaskRules.isSubmit(cache)) { info(CommonValues.INFO_CAN_NOT_RELOADED); return ;} 
					
					if (!cache.isReload() && TaskRules.isExistsReloadTask(cache)) { info(CommonValues.INFO_EXISTS_RELOAD_TASK); return ;}
					
					// clear task info
					clearTask(taskListBean);
					
					// send task message
					TaskUtils.sendTask(packTaskMessage(taskListBean));				
					
					setResponsePage(TaskListPage.class);
					
				} else if (buttonName.equals("stop")) {

					// kill process
					new TaskExecutor(packTaskMessage(taskListBean)).killTask();
					
					// update status
					DefaultImpl.updateTaskStatus(new TaskBean().setTaskNo(taskListBean.getTaskNo()),CommonValues.TASK_STATUS_FAILED);
					setResponsePage(TaskListPage.class);
					
				} else if (buttonName.equals("showResult")) {

					// go to func process page to show process result
					if (taskListBean.getTaskStatus().equalsIgnoreCase(CommonValues.TASK_STATUS_SUCCESS) && taskListBean.getCacheID() != null)
							setResponsePage(AppFuncProcessPage.class, new PageParameters().add("cacheID", taskListBean.getCacheID()).add("funcNo", taskListBean.getFuncNo()));
					else 
						info(CommonValues.INFO_TASK_NO_DATA);
					
				} else if (buttonName.equals("clearLog")) {

					// clear log before N days
					String days = CommonValues.props.getProperty("logdays").toString();
					DefaultImpl.clearLog((days==null)?CommonValues.DEFAULT_CLEAR_DAYS:Integer.parseInt(days));
					
					info(CommonValues.INFO_CLEAR_LOG);
					
				} else if (buttonName.equals("export")) {

					// export excel 
					if (taskListBean.getTaskStatus().equalsIgnoreCase(CommonValues.TASK_STATUS_SUCCESS) && taskListBean.getCacheID() != null){
						
						fileBean = new FileBean().setFuncName(taskListBean.getFuncName()).setClusterName(taskListBean.getClusterName())
									.setDsName(taskListBean.getDsName()).setParams(taskListBean.getParams());
						cacheID = taskListBean.getCacheID();
						sql = getSql(taskListBean.getFuncNo());
						flag = true;
						
					} else 
						info(CommonValues.INFO_TASK_NO_DATA);
					
				} else {
					
					// show task log page
					setResponsePage(TaskLogPage.class, new PageParameters().add("taskNo", taskListBean.getTaskNo()) );
					
				}
			}
		};
		this.add(form);
		
		// add group
		final RadioGroup<?> group=new RadioGroup<Object>("group"); 
		group.add(new AjaxSelfUpdatingTimerBehavior(Duration.seconds(CommonValues.LIST_REFRESH_TIME)){	
			
			private static final long serialVersionUID = 1L;
			
			@Override
			protected  void	onPostProcessTarget(AjaxRequestTarget target)  {
				DefaultImpl.getTasks(tasks);
				target.add(group);	
			}
			
		});
		group.setOutputMarkupId(true);
		group.setRenderBodyOnly(false);
		form.add(group);
		
		// add task list
		final PageableListView<TaskListBean> listView =new PageableListView<TaskListBean>( "rows", tasks, CommonValues.SHOW_LIST_NUMBER) {

			private static final long serialVersionUID = 1L;

			@Override
			protected void populateItem(ListItem<TaskListBean> item) {
				final TaskListBean taskListBean = (TaskListBean) item.getModelObject();
				item.add(new Radio<TaskListBean>("radio", new Model<TaskListBean>(taskListBean)));
				item.add( new Label( "taskNo", taskListBean.getTaskNo()));
				item.add( new Label( "appName", taskListBean.getAppName()));
				item.add( new Label( "funcName",taskListBean.getFuncName()));
				item.add( new Label( "params", taskListBean.getParams()));
				item.add( new Label( "clusterName", taskListBean.getClusterName()));
				item.add( new Label( "dsName", taskListBean.getDsName()));
				item.add( new Label( "userName", taskListBean.getUserName()));
				item.add( new Label( "taskStatus", CommonValues.taskStatusNames.get(taskListBean.getTaskStatus())));
				item.add( new Label( "reload", CommonValues.booleanNames.get(taskListBean.getReload())));
				item.add( new Label( "createTime", taskListBean.getCreateTime()));
				item.add( new Label( "startTime", taskListBean.getStartTime()));
				item.add( new Label( "endTime", taskListBean.getEndTime()));
			}
		};
		listView.setOutputMarkupId(true);
		group.add(listView);
		
		// add navigator
		final AjaxPagingNavigator nav = new AjaxPagingNavigator("navigator", listView);
		nav.setOutputMarkupId(true);
		group.add(nav);
		
		 // file window
		final ModalWindow modal = new ModalWindow("modal");
       this.add(modal);

       modal.setTitle("选择导出路径");
       modal.setCookieName("modal");

       modal.setCloseButtonCallback(new ModalWindow.CloseButtonCallback()
       {
			private static final long serialVersionUID = 1L;

			@Override
           public boolean onCloseButtonClicked(AjaxRequestTarget target)
           {				
			   flag = false;
               return true;
           }
       });
       
		// add button 
		form.add(new Button("reSubmit"));
		form.add(new Button("stop"));
		form.add(new Button("showLog"));
		
		// get user info from metadb
		final UserBean user = DefaultImpl.getUserInfo(CommonValues.getUserNo());
		
		Button showResult = new Button("showResult");
		form.add(showResult);
		
		Button clearLog = new Button("clearLog");
		clearLog.setVisible(false);
		form.add(clearLog);
		
		if (user.getUserType().equalsIgnoreCase("admin")) {
			showResult.setVisible(false);
			clearLog.setVisible(true);
		}
			
				
		// add refresh
		form.add(new AjaxLink<Object>("refresh"){
			private static final long serialVersionUID = 1L;
			public void onClick(AjaxRequestTarget target) {
				DefaultImpl.getTasks(tasks);
				target.add(group);
			}
		});	
		
		// export
		form.add(new AjaxButton("export"){

			private static final long serialVersionUID = 1L;

			@Override
			public void onAfterSubmit(AjaxRequestTarget target, Form<?> form) {

				if (flag) {
					modal.setContent(new ExportPanel(modal.getContentId(),fileBean,headers,cacheID, sql, modal));
					modal.show(target);
				}
			}});
		
	}
	
	protected void clearTask(TaskListBean taskListBean) {
		
		// delete cache
		TaskUtils.clearCache(taskListBean.getFuncNo(), taskListBean.getDsNo(), taskListBean.getClusterID(), taskListBean.getParams());
		
		// delete task log
		DefaultImpl.deleteTaskLog(taskListBean.getTaskNo());

		// delete task job
		DefaultImpl.deleteTaskJob(taskListBean.getTaskNo());
		
	}

	private TaskMessage packTaskMessage(TaskListBean taskListBean){
		
		return new TaskMessage().setTaskNo(taskListBean.getTaskNo())
                .setUserNo(taskListBean.getUserNo())
				 .setFuncNo(taskListBean.getFuncNo())
				 .setClusterID(taskListBean.getClusterID())
				 .setDsNo(taskListBean.getDsNo())
				 .setParams(taskListBean.getParams())
				 .setPreFailedStatus(taskListBean.getPreFailedStatus())
				 .setCacheID(taskListBean.getCacheID())
				 .setReload(taskListBean.getReload().equalsIgnoreCase("true")?true:false);
		
	}

	private String getSql(String funcNo) {

		List<ResultBean> resultColumns = Lists.newArrayList();
		StringBuffer sb = new StringBuffer(" select ");
		String orderBy = null;
		int i = 1;
		
		// get result column from meta by funcNo
		DefaultImpl.getFuncColumnList(funcNo, resultColumns);
	
		for (ResultBean column:resultColumns){
			
			headers.add(column.getColumnName());
					
			sb.append( ((i==1)?"":",") + column.getColumnCode());
			
			if (column.getIsOrder().equalsIgnoreCase("y")) {
				orderBy = ((orderBy == null)?"":(orderBy + ",")) +column.getColumnCode();
			}
			
			if (i == resultColumns.size()) {
				sb.append(" from ");
				sb.append(column.getTableName());
				sb.append(" where cache_id = 'null'");
				if (orderBy != null)
					sb.append(" order by " + orderBy);
			}
			
			i++;		
		}
			
		return sb.toString();
	}
	
}
